package com.closer.server.biz.user.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.closer.server.biz.user.dto.*;
import com.closer.server.biz.user.dto.vo.UserVO;
import com.closer.server.biz.user.service.UserRoleService;
import com.closer.server.biz.user.service.UserStatisticsService;
import com.closer.server.biz.user.validator.UserValidator;
import com.closer.server.mapper.user.RoleMapper;
import com.closer.server.mapper.user.UserRoleMapper;
import com.closer.server.mapper.user.UserStatisticsMapper;
import com.closer.server.support.exception.BusinessException;
import com.closer.server.support.exception.ErrorCode;
import com.closer.server.support.exception.ThrowUtils;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.closer.server.biz.user.entity.User;
import com.closer.server.mapper.user.UserMapper;
import com.closer.server.biz.user.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;


/**
 * 用户 服务层实现。
 *
 * @author closer
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User>  implements UserService{

    private final UserValidator validator;

    private final UserStatisticsService statisticsService;

    private final UserRoleService roleService;

    private final RoleMapper roleMapper;
    private final UserRoleMapper userRoleMapper;
    private final UserStatisticsMapper userStatisticsMapper;

    public UserServiceImpl(UserValidator validator, UserStatisticsService statisticsService, UserRoleService roleService, RoleMapper roleMapper, UserRoleMapper userRoleMapper, UserStatisticsMapper userStatisticsMapper) {
        this.validator = validator;
        this.statisticsService = statisticsService;
        this.roleService = roleService;
        this.roleMapper = roleMapper;
        this.userRoleMapper = userRoleMapper;
        this.userStatisticsMapper = userStatisticsMapper;
    }

    @Override
    @Transactional
    public long register(RegisterRequest params) {
        var account = params.getAccount();
        var password = params.getPassword();
        validator.validate(account, password, params.getCheckPassword());

        var encryptPassword = getEncryptPassword(account,password);
        var user = User.builder()
                .account(account)
                .password(encryptPassword)
                .name("用户_" + account)
                .build();
        var result = this.save(user);
        statisticsService.saveStatistics(user.getId());
        roleService.saveUserRole(user.getId(),roleMapper.getRoleId("ROLE_USER"));
        ThrowUtils.throwIf(!result, ErrorCode.SYSTEM_ERROR,"用户注册失败");
        return user.getId();

    }

    @Override
    public UserVO login(LoginRequest params) {
        var account = params.getAccount();
        var password = params.getPassword();
        validator.validate(account,password);
        var encryptPassword = getEncryptPassword(account,password);
        var userInfo = this.mapper.getUserInfo(account,encryptPassword);
        ThrowUtils.throwIf(userInfo==null, ErrorCode.OPERATION_ERROR,"用户不存在");
        StpUtil.login(userInfo.getId());
        log.info(String.valueOf(StpUtil.getRoleList()));
        return userInfo;
    }

    @Override
    public boolean logout() {
        ThrowUtils.throwIf(!StpUtil.isLogin(), ErrorCode.OPERATION_ERROR,"用户未登录");
        StpUtil.logout();
        return true;
    }

    @Override
    public UserVO getLoginInfo(Long userId) {
        validator.validate(userId);
        return this.mapper.getUserInfoById(userId);
    }

    @Override
    public boolean updateLoginInfo(UpdateRequest params) {
        validator.validate(params.getUserId(), params.getName(), params.getGender(), params.getProfile(), params.getEmail());
        var result = this.updateById(User.builder()
                .id(params.getUserId())
                .name(params.getName())
                .gender(params.getGender())
                .profile(params.getProfile())
                .email(params.getEmail())
                .build());
        ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR,"用户信息更新失败");
        return true;
    }

    @Override
    @Transactional
    public boolean updateByAdmin(UpdateByAdminRequest params) {
        validator.validate(params.getUserId(), params.getName(), params.getGender(), params.getProfile(), params.getEmail(), params.getRole());
        var result = this.updateById(User.builder()
                .id(params.getUserId())
                .name(params.getName())
                .gender(params.getGender())
                .profile(params.getProfile())
                .email(params.getEmail())
                .build());
        var roleResult = userRoleMapper.updateByAdmin(params.getUserId(),roleMapper.getRoleId(params.getRole()));
        ThrowUtils.throwIf(roleResult<=0, ErrorCode.OPERATION_ERROR,"用户角色更新失败");
        return true;
    }

    @Override
    public Page<UserVO> search(SearchRequest params) {
        validator.validate(params);
        return this.mapper.getUserVOList(params);
    }

    @Override
    @Transactional
    public long add(AddRequest params) {
        var account = params.getAccount();
        var password = params.getPassword();
        validator.checkAccAndPwd(account, password);
        ThrowUtils.throwIf(mapper.existByAccount(account)>0, ErrorCode.OPERATION_ERROR, "账号已存在");
        var encryptPassword = getEncryptPassword(account,password);
        var user = User.builder()
                .account(account)
                .password(encryptPassword)
                .name("用户_" + account)
                .build();
        var result = this.save(user);
        statisticsService.saveStatistics(user.getId());
        roleService.saveUserRole(user.getId(),roleMapper.getRoleId("ROLE_USER"));
        ThrowUtils.throwIf(!result, ErrorCode.SYSTEM_ERROR,"添加用户新失败");
        return user.getId();
    }

    @Override
    @Transactional
    public boolean delete(Long id) {
        ThrowUtils.throwIf(!StpUtil.isLogin(), ErrorCode.OPERATION_ERROR,"用户未登录");
        ThrowUtils.throwIf(StpUtil.getLoginIdAsLong() == id, ErrorCode.OPERATION_ERROR,"用户不能删除自己");
        var roles = StpUtil.getRoleList(id);
        ThrowUtils.throwIf(roles != null && roles.contains("ROLE_SUPER_ADMIN"),
                ErrorCode.OPERATION_ERROR, "不能删除超级管理员用户");
        // 检查用户是否存在
        User user = this.getById(id);
        if (user == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "用户不存在");
        }
        // 执行删除操作
        boolean result = this.removeById(id);
            userStatisticsMapper.deleteByUserId(id);
            userRoleMapper.deleteByUserId(id);
        ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR, "用户删除失败");
        return true;
    }

    @Override
    public String getEncryptPassword(String account,String userPassword) {
        var SALT = "onlineJudge";
        return DigestUtils.md5DigestAsHex((SALT + userPassword+account).getBytes());
    }
}
